package ca.michaelmaguire.server.mobiledownload.server;

import org.apache.commons.fileupload.FileItemStream;
import org.apache.commons.fileupload.FileItemIterator;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import com.google.appengine.api.datastore.Blob;
import com.google.appengine.api.datastore.Key;

import ca.michaelmaguire.server.mobiledownload.server.entity.AppContents;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.util.Date;
import java.util.logging.Logger;

import javax.jdo.JDOObjectNotFoundException;
import javax.jdo.PersistenceManager;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;

import java.util.Properties;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

/**
 * From http://code.google.com/appengine/kb/java.html#fileforms
 */
public class FileUploadServlet extends HttpServlet {
	private static final boolean EMAIL_NOTIFICATION = false;

	/**
	 * 
	 */
	private static final long serialVersionUID = -808891573175346118L;
	private static final Logger log = Logger.getLogger(FileUploadServlet.class
			.getName());

	public void doPost(HttpServletRequest aHttpServletRequest,
			HttpServletResponse aHttpServletResponse) throws ServletException,
			IOException {
		try {
			String responseString = null;

			User user = null;

			UserService userService = UserServiceFactory.getUserService();
			if (userService.isUserLoggedIn()) {
				user = userService.getCurrentUser();

				ServletFileUpload upload = new ServletFileUpload();

				Key firstAppContentsKey = null;

				FileItemIterator iterator = upload
						.getItemIterator(aHttpServletRequest);
				while (iterator.hasNext()) {
					FileItemStream item = iterator.next();
					InputStream stream = item.openStream();

					if (item.isFormField()) {
						log.warning("Got a form field: " + item.getFieldName());
					} else {
						log.warning("Got an uploaded file: "
								+ item.getFieldName() + ", name = "
								+ item.getName());

						// You now have the filename (item.getName() and the
						// contents (which you can read from stream). Here we
						// just
						// print them back out to the servlet output stream, but
						// you
						// will probably want to do something more interesting
						// (for
						// example, wrap them in a Blob and commit them to the
						// datastore).

						AppContents appContents = new AppContents();
						ByteArrayOutputStream baos = new ByteArrayOutputStream();
						int len;
						byte[] buffer = new byte[8192];
						while ((len = stream.read(buffer, 0, buffer.length)) != -1) {
							baos.write(buffer, 0, len);
						}
						Blob blob = new Blob(baos.toByteArray());
						appContents.setCreated(new Date());
						appContents.setFileName(item.getName());
						appContents.setContent(blob);
						appContents.setUser(user);
						if (null != firstAppContentsKey) {
							// This was a secondary file.
							appContents
									.setParentAppContents(firstAppContentsKey);
						}

						PersistenceManager pm = PMF.get()
								.getPersistenceManager();
						try {
							pm.makePersistent(appContents);
						} finally {
							pm.close();
						}

						if (null == firstAppContentsKey) {
							// It was first file.
							// Save away Key in case we read
							// secondary.
							firstAppContentsKey = appContents.getKey();
						} else {
							// This was a secondary file -- modify first file to
							// point to secondary.
							pm = PMF.get().getPersistenceManager();
							try {
								AppContents firstAppContents = pm
										.getObjectById(AppContents.class,
												firstAppContentsKey);
								firstAppContents
										.setSecondaryAppContents(appContents
												.getKey());
							} catch (JDOObjectNotFoundException e) {
								log
										.warning("First AppContents object is missing");
							} finally {
								pm.close();
							}

						}

						responseString = "User [" + user.getNickname()
								+ "] just uploaded file [" + item.getName()
								+ "].";

						if (EMAIL_NOTIFICATION) {
							try {
								Properties props = new Properties();
								Session session = Session.getDefaultInstance(
										props, null);
								Message msg = new MimeMessage(session);
								msg
										.setFrom(new InternetAddress(user
												.getEmail(),
												"MobileDownload Admin"));
								msg.addRecipient(Message.RecipientType.TO,
										new InternetAddress(user.getEmail(),
												user.getNickname()));
								msg
										.setSubject("[Mobile Download] Uploaded file");
								msg.setText(responseString);
								Transport.send(msg);

							} catch (AddressException e) {
								// ...
							} catch (MessagingException e) {
								// ...
							}
						}

					}

				}

			} else {
				// This re-direct doesn't seem to be working properly, but
				// isn't too important given that we don't usually get to the
				// post that hits this servlet unless we started from
				// FileUpload.html
				// which is already protected using security-constraint in
				// web.xml.
				responseString = "Please <a href="
						+ userService.createLoginURL("/admin/FileUpload.html")
						+ ">log in</a>";

			}

			aHttpServletResponse.setContentType("text/html");
			ServletOutputStream sos = aHttpServletResponse.getOutputStream();
			sos.write(responseString.getBytes());

		} catch (Exception aException) {
			throw new ServletException(aException);
		}
	}
}